
<!DOCTYPE html>
<html
  lang="zh-cn"
  data-figures=""
  
    class="page"
  
  
  >
  <head>
<title>Linux内核驱动模型（三）驱动初始化 | 拾月国度</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script>
  var _hmt = _hmt || [];
  (function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?c24bad48a3da8c3c532f0c580bb4f8c5";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
  })();
</script>





<meta property="og:locale" content="zh-cn" />

<meta property="og:type" content="article">
<meta name="description" content="initcall和module_init" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="">
<meta name="twitter:title" content="Linux内核驱动模型（三）驱动初始化" />
<meta name="twitter:image" content="https://kingdix10.gitee.io/covers/cover8.jpg"/>
<meta property="og:url" content="https://kingdix10.gitee.io/post/kernel/linux-6.1/device_driver/initcall/" />
<meta property="og:title" content="Linux内核驱动模型（三）驱动初始化" />
<meta property="og:description" content="initcall和module_init" />
<meta property="og:image" content="https://kingdix10.gitee.io/covers/cover8.jpg" />

<link rel="apple-touch-icon" sizes="180x180" href="https://kingdix10.gitee.io/icons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://kingdix10.gitee.io/icons/icon_yellow_transparent.png">
<link rel="manifest" href="https://kingdix10.gitee.io/icons/site.webmanifest">

<link rel="canonical" href="https://kingdix10.gitee.io/post/kernel/linux-6.1/device_driver/initcall/">



<link rel="preload" href="https://kingdix10.gitee.io/css/styles.42e2c5f6d8cf9c52872666f8d8b2678ad0c426978b9d78aff3c33b7a1e7f6f97f54bcdaf0518a25fb0fe26367d04f8b07c683b3b38b331cb098daadee06b1f3e.css" integrity = "sha512-QuLF9tjPnFKHJmb42LJnitDEJpeLnXiv88M7eh5/b5f1S82vBRiiX7D&#43;JjZ9BPiwfGg7OzizMcsJjare4GsfPg==" as="style" crossorigin="anonymous">



<link rel="preload" href="https://kingdix10.gitee.io/zh-cn/js/bundle.352f6b8ac853443fc909370d968a769ffa303b36042cc66849f2d48d9e5dd951ee86c06130908f5d77ea0e55ec8fed0e5dc26f0f14bbd4ad6dcf35999232e5bc.js" as="script" integrity=
"sha512-NS9rishTRD/JCTcNlop2n/owOzYELMZoSfLUjZ5d2VHuhsBhMJCPXXfqDlXsj&#43;0OXcJvDxS71K1tzzWZkjLlvA==" crossorigin="anonymous">


<link rel="stylesheet" type="text/css" href="https://kingdix10.gitee.io/css/styles.42e2c5f6d8cf9c52872666f8d8b2678ad0c426978b9d78aff3c33b7a1e7f6f97f54bcdaf0518a25fb0fe26367d04f8b07c683b3b38b331cb098daadee06b1f3e.css" integrity="sha512-QuLF9tjPnFKHJmb42LJnitDEJpeLnXiv88M7eh5/b5f1S82vBRiiX7D&#43;JjZ9BPiwfGg7OzizMcsJjare4GsfPg==" crossorigin="anonymous">

  </head>
  <body
    data-code="9"
    data-lines="true"
    id="documentTop"
    data-lang="zh-cn"
  >

<header class="nav_header" >
  <nav class="nav"><a href='https://kingdix10.gitee.io/' class="nav_brand nav_item" title="拾月国度">
  <img src="https://kingdix10.gitee.io/logos/icon_yellow_transparent_72x72.png" class="logo" alt="拾月国度">
  <div class="nav_close">
    <div><svg class="icon">
  <title>open-menu</title>
  <use xlink:href="#open-menu"></use>
</svg>
<svg class="icon">
  <title>closeme</title>
  <use xlink:href="#closeme"></use>
</svg>
</div>
  </div>
</a>

    <div class='nav_body nav_body_left'>
      
      
      
        

  <div class="nav_parent">
    <a href="https://kingdix10.gitee.io/home" class="nav_item" title="主页">主页 </a>
  </div>
  <div class="nav_parent">
    <a href="https://kingdix10.gitee.io/" class="nav_item" title="归档">归档 </a>
  </div>
  <div class="nav_parent">
    <a href="https://kingdix10.gitee.io/" class="nav_item" title="链接">链接 <img src='https://kingdix10.gitee.io/icons/caret-icon.svg' alt="icon" class="nav_icon"></a>
    <div class="nav_sub">
      <span class="nav_child"></span>
        <a href="https://gitee.com/kingdix10" class="nav_child nav_item" title="Gitee">Gitee</a>
        <a href="https://github.com/kingdix10" class="nav_child nav_item" title="GitHub">GitHub</a>
        <a href="https://www.zhihu.com/people/kingdix10" class="nav_child nav_item" title="知乎">知乎</a>
        <a href="https://www.cnblogs.com/kingdix10" class="nav_child nav_item" title="博客园">博客园</a>
        <a href="https://blog.csdn.net/u014001096" class="nav_child nav_item" title="CSDN">CSDN</a>
    </div>
  </div>
  <div class="nav_parent">
    <a href="https://kingdix10.gitee.io/about/" class="nav_item" title="关于">关于 </a>
  </div>
      
      <div class="nav_parent">
        <a href="#" class="nav_item">🌐</a>
        <div class="nav_sub">
          <span class="nav_child"></span>
          
          <a href="https://kingdix10.gitee.io/" class="nav_child nav_item">中文</a>
          
          <a href="https://kingdix10.gitee.io/en/" class="nav_child nav_item">English</a>
          
        </div>
      </div>
<div class='follow'>
  <a href="https://gitee.com/kingdix10">
    <svg class="icon">
  <title>gitee</title>
  <use xlink:href="#gitee"></use>
</svg>

  </a>
  <a href="https://github.com/kingdix10">
    <svg class="icon">
  <title>github</title>
  <use xlink:href="#github"></use>
</svg>

  </a>
    
  <a href="https://kingdix10.gitee.io/index.xml">
    <svg class="icon">
  <title>rss</title>
  <use xlink:href="#rss"></use>
</svg>

  </a>
<div class="color_mode">
  <input type="checkbox" class="color_choice" id="mode">
</div>

</div>

    </div>
  </nav>
</header>

    <main>
<div class="grid-inverse wrap content">
  <article class="post_content">
    <h1 class="post_title">Linux内核驱动模型（三）驱动初始化</h1>
  <div class="post_meta">
    <span><svg class="icon">
  <title>calendar</title>
  <use xlink:href="#calendar"></use>
</svg>
</span>
    <span class="post_date">
      2022/08/12</span>
    <span class="post_time"> | 9 分钟阅读</span><span>&nbsp;|<a href='https://kingdix10.gitee.io/tags/linux%E5%86%85%E6%A0%B8/' title="linux内核" class="post_tag button button_translucent">linux内核
        </a><a href='https://kingdix10.gitee.io/tags/%E5%86%85%E6%A0%B8%E9%A9%B1%E5%8A%A8/' title="内核驱动" class="post_tag button button_translucent">内核驱动
        </a><a href='https://kingdix10.gitee.io/tags/linux-6.1/' title="linux-6.1" class="post_tag button button_translucent">linux-6.1
        </a>
    </span>
    <span class="page_only">&nbsp;|
  <div class="post_share">
    分享到:

    <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/device_driver/initcall/" title="Copy Link" class="link link_yank">
      <svg class="icon">
  <title>copy</title>
  <use xlink:href="#copy"></use>
</svg>

    </a>
  </div>
  
</span>
  </div>



      <div class="post_toc">
        <h2>文章目录</h2>
        <nav id="TableOfContents">
  <ul>
    <li><a href="#1-module_init是什么">1. module_init是什么</a>
      <ul>
        <li><a href="#11-module的定义">1.1. MODULE的定义</a></li>
      </ul>
    </li>
    <li><a href="#2-module未使能">2. MODULE未使能</a>
      <ul>
        <li><a href="#21-initcall分析">2.1. initcall分析</a></li>
        <li><a href="#22-initcall的源码">2.2. initcall的源码</a></li>
        <li><a href="#23-rootfs_initcall是什么">2.3. rootfs_initcall是什么</a></li>
        <li><a href="#24-console_initcall">2.4. console_initcall</a></li>
        <li><a href="#25-链接脚本中initcall段">2.5. 链接脚本中initcall段</a></li>
        <li><a href="#26-initcall的执行时机">2.6. initcall的执行时机</a></li>
      </ul>
    </li>
    <li><a href="#3-module使能">3. MODULE使能</a>
      <ul>
        <li><a href="#31-module_init源码">3.1. module_init源码</a></li>
        <li><a href="#32-init_module的执行时机">3.2. init_module的执行时机</a></li>
      </ul>
    </li>
    <li><a href="#4-参考资料">4. 参考资料</a></li>
  </ul>
</nav>
      </div>
    
    <div class="post_body"><h1 id="1-module_init是什么">1. module_init是什么</h1>
<p>module_init是Linux内核开发和驱动开发中非常常见的宏，其定义在 <code>include/linux/module.h</code>中，可以看到，module_init的实现会根据是否定义MODULE而有所不同。MODULE决定了我们编写的驱动，是与内核编译到一起，还是单独编译为ko。</p>
<h2 id="11-module的定义">1.1. MODULE的定义</h2>
<p>MODULE是通过在编译时，通过编译器的参数来传入的。如下是Makefile中的内容，在编译ko时，会使用如下两个编译选项，如果是链接到内核，则不会使用如下选项。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">/// Makefile
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="nl">KBUILD_AFLAGS_MODULE</span>  <span class="p">:</span><span class="o">=</span> <span class="o">-</span><span class="n">DMODULE</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nl">KBUILD_CFLAGS_MODULE</span>  <span class="p">:</span><span class="o">=</span> <span class="o">-</span><span class="n">DMODULE</span>
</span></span></code></pre></div><p>如果想看编译某个文件时是否由 <code>-DMODULE</code>选项，可以直接查看编译生成 <code>.xxx.o.cmd</code>文件。</p>
<p>下面先分析MODULE未使能的情况。</p>
<h1 id="2-module未使能">2. MODULE未使能</h1>
<p>MODULE未定义的情况下，module_init是一种特殊的initcall。initcall是内核用于声明初始化函数以及控制函数调用顺序的机制。
initcall有多个级别，module_init实际就是device_initcall，其级别为6。initcall最终会声明一个initcall_t静态变量，链接时放到内核的 <code>.init.data</code>段。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// include/linux/module.h
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cp">#ifndef MODULE
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span><span class="cm">/**
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cm"> * module_init() - driver initialization entry point
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cm"> * @x: function to be run at kernel boot time or module insertion
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="cm"> * module_init() will either be called during do_initcalls() (if
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="cm"> * builtin) or at module insertion time (if a module).  There can only
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="cm"> * be one per module.
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="cp">#define module_init(x)  __initcall(x);
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="cm"> * module_exit() - driver exit entry point
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="cm"> * @x: function to be run when driver is removed
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="cm"> * module_exit() will wrap the driver clean-up code
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="cm"> * with cleanup_module() when used with rmmod when
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="cm"> * the driver is a module.  If the driver is statically
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="cm"> * compiled into the kernel, module_exit() has no effect.
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="cm"> * There can only be one per module.
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="cp">#define module_exit(x)  __exitcall(x);
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="cp">#else </span><span class="cm">/* MODULE */</span><span class="cp">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="cp"></span><span class="c1">/// ... ...
</span></span></span></code></pre></div><h2 id="21-initcall分析">2.1. initcall分析</h2>
<p>首先通过 <code>arch64-linux-gnu-nm -n vmlinux | grep -E -C 2 '_initcall.*(_start|_end)$'</code>来看一下编译的最终结果。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="ln"> 1</span><span class="cl">ffff8000094fc228 d __setup_debug_boot_weak_hash_enable
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">ffff8000094fc240 d __initcall__kmod_ptrace__414_42_trace_init_flags_sys_enterearly
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">ffff8000094fc240 D __initcall_start
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">ffff8000094fc240 D __setup_end
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">ffff8000094fc244 d __initcall__kmod_ptrace__416_66_trace_init_flags_sys_exitearly
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">--
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">ffff8000094fc2a8 d __initcall__kmod_earlycon__376_41_efi_earlycon_remap_fbearly
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">ffff8000094fc2ac d __initcall__kmod_dummy_timer__364_37_dummy_timer_registerearly
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">ffff8000094fc2b0 D __initcall0_start
</span></span><span class="line"><span class="ln">10</span><span class="cl">ffff8000094fc2b0 d __initcall__kmod_core__527_975_bpf_jit_charge_init0
</span></span><span class="line"><span class="ln">11</span><span class="cl">ffff8000094fc2b4 d __initcall__kmod_shm__486_153_ipc_ns_init0
</span></span><span class="line"><span class="ln">12</span><span class="cl">--
</span></span><span class="line"><span class="ln">13</span><span class="cl">ffff8000094fc2bc d __initcall__kmod_pci__516_6911_pci_realloc_setup_params0
</span></span><span class="line"><span class="ln">14</span><span class="cl">ffff8000094fc2c0 d __initcall__kmod_inet_fragment__696_216_inet_frag_wq_init0
</span></span><span class="line"><span class="ln">15</span><span class="cl">ffff8000094fc2c4 D __initcall1_start
</span></span><span class="line"><span class="ln">16</span><span class="cl">ffff8000094fc2c4 d __initcall__kmod_fpsimd__388_2058_fpsimd_init1
</span></span><span class="line"><span class="ln">17</span><span class="cl">ffff8000094fc2c8 d __initcall__kmod_process__462_734_tagged_addr_init1
</span></span><span class="line"><span class="ln">18</span><span class="cl">--
</span></span><span class="line"><span class="ln">19</span><span class="cl">ffff8000094fc3cc d __initcall__kmod_genetlink__620_1498_genl_init1
</span></span><span class="line"><span class="ln">20</span><span class="cl">ffff8000094fc3d0 d __initcall__kmod_trace_boot__394_671_trace_boot_init1s
</span></span><span class="line"><span class="ln">21</span><span class="cl">ffff8000094fc3d4 D __initcall2_start
</span></span><span class="line"><span class="ln">22</span><span class="cl">ffff8000094fc3d4 d __initcall__kmod_debug_monitors__391_139_debug_monitors_init2
</span></span><span class="line"><span class="ln">23</span><span class="cl">ffff8000094fc3d8 d __initcall__kmod_index__322_194_pi_init2
</span></span><span class="line"><span class="ln">24</span><span class="cl">--
</span></span><span class="line"><span class="ln">25</span><span class="cl">ffff8000094fc460 d __initcall__kmod_rpmsg_core__351_710_rpmsg_init2
</span></span><span class="line"><span class="ln">26</span><span class="cl">ffff8000094fc464 d __initcall__kmod_kobject_uevent__622_814_kobject_uevent_init2
</span></span><span class="line"><span class="ln">27</span><span class="cl">ffff8000094fc468 D __initcall3_start
</span></span><span class="line"><span class="ln">28</span><span class="cl">ffff8000094fc468 d __initcall__kmod_setup__397_281_reserve_memblock_reserved_regions3
</span></span><span class="line"><span class="ln">29</span><span class="cl">ffff8000094fc46c d __initcall__kmod_vdso__390_363_aarch32_alloc_vdso_pages3
</span></span><span class="line"><span class="ln">30</span><span class="cl">--
</span></span><span class="line"><span class="ln">31</span><span class="cl">ffff8000094fc4a8 d __initcall__kmod_dmi_id__332_259_dmi_id_init3
</span></span><span class="line"><span class="ln">32</span><span class="cl">ffff8000094fc4ac d __initcall__kmod_platform__462_596_of_platform_default_populate_init3s
</span></span><span class="line"><span class="ln">33</span><span class="cl">ffff8000094fc4b0 D __initcall4_start
</span></span><span class="line"><span class="ln">34</span><span class="cl">ffff8000094fc4b0 d __initcall__kmod_setup__399_406_topology_init4
</span></span><span class="line"><span class="ln">35</span><span class="cl">ffff8000094fc4b4 d __initcall__kmod_mte__458_603_register_mte_tcf_preferred_sysctl4
</span></span><span class="line"><span class="ln">36</span><span class="cl">--
</span></span><span class="line"><span class="ln">37</span><span class="cl">ffff8000094fc694 d __initcall__kmod_vgaarb__423_1564_vga_arb_device_init4s
</span></span><span class="line"><span class="ln">38</span><span class="cl">ffff8000094fc698 d __initcall__kmod_watchdog__465_479_watchdog_init4s
</span></span><span class="line"><span class="ln">39</span><span class="cl">ffff8000094fc69c D __initcall5_start
</span></span><span class="line"><span class="ln">40</span><span class="cl">ffff8000094fc69c d __initcall__kmod_debug_monitors__389_63_create_debug_debugfs_entry5
</span></span><span class="line"><span class="ln">41</span><span class="cl">ffff8000094fc6a0 d __initcall__kmod_resource__402_2029_iomem_init_inode5
</span></span><span class="line"><span class="ln">42</span><span class="cl">--
</span></span><span class="line"><span class="ln">43</span><span class="cl">ffff8000094fc784 d __initcall__kmod_acpi__398_141_acpi_reserve_resources5s
</span></span><span class="line"><span class="ln">44</span><span class="cl">ffff8000094fc788 d __initcall__kmod_initramfs__399_762_populate_rootfsrootfs
</span></span><span class="line"><span class="ln">45</span><span class="cl">ffff8000094fc788 D __initcallrootfs_start
</span></span><span class="line"><span class="ln">46</span><span class="cl">ffff8000094fc78c D __initcall6_start
</span></span><span class="line"><span class="ln">47</span><span class="cl">ffff8000094fc78c d __initcall__kmod_setup__401_440_register_arm64_panic_block6
</span></span><span class="line"><span class="ln">48</span><span class="cl">ffff8000094fc790 d __initcall__kmod_cpuinfo__334_359_cpuinfo_regs_init6
</span></span><span class="line"><span class="ln">49</span><span class="cl">--
</span></span><span class="line"><span class="ln">50</span><span class="cl">ffff8000094fcd40 d __initcall__kmod_9pnet_virtio__634_831_p9_virtio_init6
</span></span><span class="line"><span class="ln">51</span><span class="cl">ffff8000094fcd44 d __initcall__kmod_dns_resolver__330_382_init_dns_resolver6
</span></span><span class="line"><span class="ln">52</span><span class="cl">ffff8000094fcd48 D __initcall7_start
</span></span><span class="line"><span class="ln">53</span><span class="cl">ffff8000094fcd48 d __initcall__kmod_mounts__426_40_kernel_do_mounts_initrd_sysctls_init7
</span></span><span class="line"><span class="ln">54</span><span class="cl">ffff8000094fcd4c d __initcall__kmod_panic__390_97_kernel_panic_sysctls_init7
</span></span><span class="line"><span class="ln">55</span><span class="cl">--
</span></span><span class="line"><span class="ln">56</span><span class="cl">ffff8000094fce6c d __initcall__kmod_core__606_6212_regulator_init_complete7s
</span></span><span class="line"><span class="ln">57</span><span class="cl">ffff8000094fce70 d __initcall__kmod_platform__464_603_of_platform_sync_state_init7s
</span></span><span class="line"><span class="ln">58</span><span class="cl">ffff8000094fce74 D __con_initcall_start
</span></span><span class="line"><span class="ln">59</span><span class="cl">ffff8000094fce74 d __initcall__kmod_vt__408_3548_con_initcon
</span></span><span class="line"><span class="ln">60</span><span class="cl">ffff8000094fce74 D __initcall_end
</span></span><span class="line"><span class="ln">61</span><span class="cl">ffff8000094fce78 d __initcall__kmod_hvc_console__376_246_hvc_console_initcon
</span></span><span class="line"><span class="ln">62</span><span class="cl">ffff8000094fce7c d __initcall__kmod_8250__387_690_univ8250_console_initcon
</span></span><span class="line"><span class="ln">63</span><span class="cl">ffff8000094fce80 D __con_initcall_end
</span></span><span class="line"><span class="ln">64</span><span class="cl">ffff8000094fce80 D __initramfs_start
</span></span></code></pre></div><p>以 <code>__initcall__kmod_cpuinfo__334_359_cpuinfo_regs_init6</code>为例来说明一下module_init的效果。</p>
<p><code>__initcall__kmod_cpuinfo__334_359_cpuinfo_regs_init6</code>是一个initcall_t类型的静态变量，变量名称可以由 <code>__initcall_name(initcall, __initcall_id(fn), id)</code>得出。</p>
<p>将变量名拆分开来可得：<code>__ initcall __ [kmod_cpuinfo __ 334 _ 359 _ cpuinfo_regs_init] 6</code>，<code>[]</code>内的内容由 <code>__initcall_id(fn)</code>生成，其格式为 <code>&lt;modname&gt;__&lt;counter&gt;_&lt;line&gt;_&lt;fn&gt;</code>：</p>
<ul>
<li>modname：<code>__KBUILD_MODNAME</code>，来自于 <code>scripts/Makefile.lib:127:  -D__KBUILD_MODNAME=kmod_$(call name-fix-token,$(modname))</code>，<code>kmod_</code>是固定的，<code>__KBUILD_MODNAME</code>在这里是kmod_cpuinfo。</li>
<li>counter：来自于 <code>__COUNTER__</code>，是编译器内部定义的计数器，每使用一次 <code>__COUNTER__</code>，其值为自动加一，这里是334。</li>
<li>line：这个是声明所在的行号，对应的源码为 <code>arch/arm64/kernel/cpuinfo.c:359:device_initcall(cpuinfo_regs_init);</code>，这里是359。</li>
<li>fn：函数名，这里是cpuinfo_regs_init。</li>
</ul>
<p>除去 <code>[]</code>内的部分，变量名的其他部分由 <code>__initcall_name</code>生成，其格式为 <code>__&lt;prefix&gt;__&lt;iid&gt;&lt;id&gt;</code>：</p>
<ul>
<li>prefix：固定为initcall</li>
<li>iid：<code>__initcall_id(fn)</code>生成的内容</li>
<li>id：<code>__define_initcall</code>的第二个参数</li>
</ul>
<h2 id="22-initcall的源码">2.2. initcall的源码</h2>
<p>下面是 <code>include/linux/init.h</code>的源码，上边是以未定义CONFIG_LTO_CLANG和CONFIG_HAVE_ARCH_PREL32_RELOCATIONS来分析的。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">/// include/linux/init.h
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#ifndef MODULE
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="cp">#ifndef __ASSEMBLY__
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="cm"> * initcalls are now grouped by functionality into separate
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="cm"> * subsections. Ordering inside the subsections is determined
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="cm"> * by link order.
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="cm"> * For backwards compatibility, initcall() puts the call in
</span></span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="cm"> * the device init subsection.
</span></span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="cm"> * The `id&#39; arg to __define_initcall() is needed so that multiple initcalls
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="cm"> * can point at the same handler without causing duplicate-symbol build errors.
</span></span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="cm"> * Initcalls are run by placing pointers in initcall sections that the
</span></span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="cm"> * kernel iterates at runtime. The linker can do dead code / data elimination
</span></span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="cm"> * and remove that completely, so the initcall sections have to be marked
</span></span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="cm"> * as KEEP() in the linker script.
</span></span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">
</span></span><span class="line"><span class="ln"> 22</span><span class="cl"><span class="cm">/* Format: &lt;modname&gt;__&lt;counter&gt;_&lt;line&gt;_&lt;fn&gt; */</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl"><span class="cp">#define __initcall_id(fn)                                       \
</span></span></span><span class="line"><span class="ln"> 24</span><span class="cl"><span class="cp">        __PASTE(__KBUILD_MODNAME,                               \
</span></span></span><span class="line"><span class="ln"> 25</span><span class="cl"><span class="cp">        __PASTE(__,                                             \
</span></span></span><span class="line"><span class="ln"> 26</span><span class="cl"><span class="cp">        __PASTE(__COUNTER__,                                    \
</span></span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="cp">        __PASTE(_,                                              \
</span></span></span><span class="line"><span class="ln"> 28</span><span class="cl"><span class="cp">        __PASTE(__LINE__,                                       \
</span></span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="cp">        __PASTE(_, fn))))))
</span></span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl"><span class="cm">/* Format: __&lt;prefix&gt;__&lt;iid&gt;&lt;id&gt; */</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="cp">#define __initcall_name(prefix, __iid, id)                      \
</span></span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="cp">        __PASTE(__,                                             \
</span></span></span><span class="line"><span class="ln"> 34</span><span class="cl"><span class="cp">        __PASTE(prefix,                                         \
</span></span></span><span class="line"><span class="ln"> 35</span><span class="cl"><span class="cp">        __PASTE(__,                                             \
</span></span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="cp">        __PASTE(__iid, id))))
</span></span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="cp">#ifdef CONFIG_LTO_CLANG
</span></span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="cp"></span><span class="cm">/*
</span></span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="cm"> * With LTO, the compiler doesn&#39;t necessarily obey link order for
</span></span></span><span class="line"><span class="ln"> 41</span><span class="cl"><span class="cm"> * initcalls. In order to preserve the correct order, we add each
</span></span></span><span class="line"><span class="ln"> 42</span><span class="cl"><span class="cm"> * variable into its own section and generate a linker script (in
</span></span></span><span class="line"><span class="ln"> 43</span><span class="cl"><span class="cm"> * scripts/link-vmlinux.sh) to specify the order of the sections.
</span></span></span><span class="line"><span class="ln"> 44</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl"><span class="cp">#define __initcall_section(__sec, __iid)                        \
</span></span></span><span class="line"><span class="ln"> 46</span><span class="cl"><span class="cp">        #__sec &#34;.init..&#34; #__iid
</span></span></span><span class="line"><span class="ln"> 47</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="cm"> * With LTO, the compiler can rename static functions to avoid
</span></span></span><span class="line"><span class="ln"> 50</span><span class="cl"><span class="cm"> * global naming collisions. We use a global stub function for
</span></span></span><span class="line"><span class="ln"> 51</span><span class="cl"><span class="cm"> * initcalls to create a stable symbol name whose address can be
</span></span></span><span class="line"><span class="ln"> 52</span><span class="cl"><span class="cm"> * taken in inline assembly when PREL32 relocations are used.
</span></span></span><span class="line"><span class="ln"> 53</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl"><span class="cp">#define __initcall_stub(fn, __iid, id)                          \
</span></span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="cp">        __initcall_name(initstub, __iid, id)
</span></span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl"><span class="cp">#define __define_initcall_stub(__stub, fn)                      \
</span></span></span><span class="line"><span class="ln"> 58</span><span class="cl"><span class="cp">        int __init __stub(void);                                \
</span></span></span><span class="line"><span class="ln"> 59</span><span class="cl"><span class="cp">        int __init __stub(void)                                 \
</span></span></span><span class="line"><span class="ln"> 60</span><span class="cl"><span class="cp">        {                                                       \
</span></span></span><span class="line"><span class="ln"> 61</span><span class="cl"><span class="cp">                return fn();                                    \
</span></span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="cp">        }                                                       \
</span></span></span><span class="line"><span class="ln"> 63</span><span class="cl"><span class="cp">        __ADDRESSABLE(__stub)
</span></span></span><span class="line"><span class="ln"> 64</span><span class="cl"><span class="cp">#else
</span></span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="cp">#define __initcall_section(__sec, __iid)                        \
</span></span></span><span class="line"><span class="ln"> 66</span><span class="cl"><span class="cp">        #__sec &#34;.init&#34;
</span></span></span><span class="line"><span class="ln"> 67</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl"><span class="cp">#define __initcall_stub(fn, __iid, id)  fn
</span></span></span><span class="line"><span class="ln"> 69</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl"><span class="cp">#define __define_initcall_stub(__stub, fn)                      \
</span></span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="cp">        __ADDRESSABLE(fn)
</span></span></span><span class="line"><span class="ln"> 72</span><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="ln"> 73</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl"><span class="cp">#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
</span></span></span><span class="line"><span class="ln"> 75</span><span class="cl"><span class="cp">#define ____define_initcall(fn, __stub, __name, __sec)          \
</span></span></span><span class="line"><span class="ln"> 76</span><span class="cl"><span class="cp">        __define_initcall_stub(__stub, fn)                      \
</span></span></span><span class="line"><span class="ln"> 77</span><span class="cl"><span class="cp">        asm(&#34;.section   \&#34;&#34; __sec &#34;\&#34;, \&#34;a\&#34;            \n&#34;     \
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="cp">            __stringify(__name) &#34;:                      \n&#34;     \
</span></span></span><span class="line"><span class="ln"> 79</span><span class="cl"><span class="cp">            &#34;.long      &#34; __stringify(__stub) &#34; - .     \n&#34;     \
</span></span></span><span class="line"><span class="ln"> 80</span><span class="cl"><span class="cp">            &#34;.previous                                  \n&#34;);   \
</span></span></span><span class="line"><span class="ln"> 81</span><span class="cl"><span class="cp">        static_assert(__same_type(initcall_t, &amp;fn));
</span></span></span><span class="line"><span class="ln"> 82</span><span class="cl"><span class="cp">#else
</span></span></span><span class="line"><span class="ln"> 83</span><span class="cl"><span class="cp">#define ____define_initcall(fn, __unused, __name, __sec)        \
</span></span></span><span class="line"><span class="ln"> 84</span><span class="cl"><span class="cp">        static initcall_t __name __used                         \
</span></span></span><span class="line"><span class="ln"> 85</span><span class="cl"><span class="cp">                __attribute__((__section__(__sec))) = fn;
</span></span></span><span class="line"><span class="ln"> 86</span><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="ln"> 87</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl"><span class="cp">#define __unique_initcall(fn, id, __sec, __iid)                 \
</span></span></span><span class="line"><span class="ln"> 89</span><span class="cl"><span class="cp">        ____define_initcall(fn,                                 \
</span></span></span><span class="line"><span class="ln"> 90</span><span class="cl"><span class="cp">                __initcall_stub(fn, __iid, id),                 \
</span></span></span><span class="line"><span class="ln"> 91</span><span class="cl"><span class="cp">                __initcall_name(initcall, __iid, id),           \
</span></span></span><span class="line"><span class="ln"> 92</span><span class="cl"><span class="cp">                __initcall_section(__sec, __iid))
</span></span></span><span class="line"><span class="ln"> 93</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl"><span class="cp">#define ___define_initcall(fn, id, __sec)                       \
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="cp">        __unique_initcall(fn, id, __sec, __initcall_id(fn))
</span></span></span><span class="line"><span class="ln"> 96</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="cp">#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)
</span></span></span><span class="line"><span class="ln"> 98</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="ln">100</span><span class="cl"><span class="cm"> * Early initcalls run before initializing SMP.
</span></span></span><span class="line"><span class="ln">101</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln">102</span><span class="cl"><span class="cm"> * Only for built-in code, not modules.
</span></span></span><span class="line"><span class="ln">103</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl"><span class="cp">#define early_initcall(fn)              __define_initcall(fn, early)
</span></span></span><span class="line"><span class="ln">105</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">106</span><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="ln">107</span><span class="cl"><span class="cm"> * A &#34;pure&#34; initcall has no dependencies on anything else, and purely
</span></span></span><span class="line"><span class="ln">108</span><span class="cl"><span class="cm"> * initializes variables that couldn&#39;t be statically initialized.
</span></span></span><span class="line"><span class="ln">109</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln">110</span><span class="cl"><span class="cm"> * This only exists for built-in code, not for modules.
</span></span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="cm"> * Keep main.c:initcall_level_names[] in sync.
</span></span></span><span class="line"><span class="ln">112</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl"><span class="cp">#define pure_initcall(fn)               __define_initcall(fn, 0)
</span></span></span><span class="line"><span class="ln">114</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">115</span><span class="cl"><span class="cp">#define core_initcall(fn)               __define_initcall(fn, 1)
</span></span></span><span class="line"><span class="ln">116</span><span class="cl"><span class="cp">#define core_initcall_sync(fn)          __define_initcall(fn, 1s)
</span></span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="cp">#define postcore_initcall(fn)           __define_initcall(fn, 2)
</span></span></span><span class="line"><span class="ln">118</span><span class="cl"><span class="cp">#define postcore_initcall_sync(fn)      __define_initcall(fn, 2s)
</span></span></span><span class="line"><span class="ln">119</span><span class="cl"><span class="cp">#define arch_initcall(fn)               __define_initcall(fn, 3)
</span></span></span><span class="line"><span class="ln">120</span><span class="cl"><span class="cp">#define arch_initcall_sync(fn)          __define_initcall(fn, 3s)
</span></span></span><span class="line"><span class="ln">121</span><span class="cl"><span class="cp">#define subsys_initcall(fn)             __define_initcall(fn, 4)
</span></span></span><span class="line"><span class="ln">122</span><span class="cl"><span class="cp">#define subsys_initcall_sync(fn)        __define_initcall(fn, 4s)
</span></span></span><span class="line"><span class="ln">123</span><span class="cl"><span class="cp">#define fs_initcall(fn)                 __define_initcall(fn, 5)
</span></span></span><span class="line"><span class="ln">124</span><span class="cl"><span class="cp">#define fs_initcall_sync(fn)            __define_initcall(fn, 5s)
</span></span></span><span class="line"><span class="ln">125</span><span class="cl"><span class="cp">#define rootfs_initcall(fn)             __define_initcall(fn, rootfs)
</span></span></span><span class="line"><span class="ln">126</span><span class="cl"><span class="cp">#define device_initcall(fn)             __define_initcall(fn, 6)
</span></span></span><span class="line"><span class="ln">127</span><span class="cl"><span class="cp">#define device_initcall_sync(fn)        __define_initcall(fn, 6s)
</span></span></span><span class="line"><span class="ln">128</span><span class="cl"><span class="cp">#define late_initcall(fn)               __define_initcall(fn, 7)
</span></span></span><span class="line"><span class="ln">129</span><span class="cl"><span class="cp">#define late_initcall_sync(fn)          __define_initcall(fn, 7s)
</span></span></span><span class="line"><span class="ln">130</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">131</span><span class="cl"><span class="cp">#define __initcall(fn) device_initcall(fn)
</span></span></span><span class="line"><span class="ln">132</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">133</span><span class="cl"><span class="cp">#define __exitcall(fn)                                          \
</span></span></span><span class="line"><span class="ln">134</span><span class="cl"><span class="cp">        static exitcall_t __exitcall_##fn __exit_call = fn
</span></span></span><span class="line"><span class="ln">135</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">136</span><span class="cl"><span class="cp">#define console_initcall(fn)    ___define_initcall(fn, con, .con_initcall)
</span></span></span><span class="line"><span class="ln">137</span><span class="cl"><span class="cp"></span><span class="c1">/// ... ...
</span></span></span></code></pre></div><h2 id="23-rootfs_initcall是什么">2.3. rootfs_initcall是什么</h2>
<p>rootfs_initcall在5s之后，rootfs_initcall指向的函数也会在do_basic_setup中被调用到。rootfs要从存储介质中读取文件系统镜像，需要在执行rootfs_initcall指向的函数之前，将存储介质准备好，比如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">/// drivers/mmc/core/core.c
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="nf">subsys_initcall</span><span class="p">(</span><span class="n">mmc_init</span><span class="p">);</span>
</span></span></code></pre></div><h2 id="24-console_initcall">2.4. console_initcall</h2>
<p>为了能尽早输出日志，内核将console相关的initcall单独存放，由console_initcall声明。相关初始化函数在console_init中调用。console_init则在start_kernel中尽量选择较早的时机调用。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// kernel/printk/printk.c
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cm">/*
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cm"> * Initialize the console device. This is called *early*, so
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cm"> * we can&#39;t necessarily depend on lots of kernel help here.
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cm"> * Just do some early initializations, and do the complex setup
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cm"> * later.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kt">void</span> <span class="n">__init</span> <span class="nf">console_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="kt">initcall_t</span> <span class="n">call</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="kt">initcall_entry_t</span> <span class="o">*</span><span class="n">ce</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="cm">/* Setup the default TTY line discipline. */</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="nf">n_tty_init</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="cm">/*
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="cm">     * set up the console device so that later boot sequences can
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="cm">     * inform about problems etc..
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="cm">     */</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">ce</span> <span class="o">=</span> <span class="n">__con_initcall_start</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="nf">trace_initcall_level</span><span class="p">(</span><span class="s">&#34;console&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">ce</span> <span class="o">&lt;</span> <span class="n">__con_initcall_end</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="n">call</span> <span class="o">=</span> <span class="nf">initcall_from_entry</span><span class="p">(</span><span class="n">ce</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="nf">trace_initcall_start</span><span class="p">(</span><span class="n">call</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="n">ret</span> <span class="o">=</span> <span class="nf">call</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="nf">trace_initcall_finish</span><span class="p">(</span><span class="n">call</span><span class="p">,</span> <span class="n">ret</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">ce</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="25-链接脚本中initcall段">2.5. 链接脚本中initcall段</h2>
<p>initcall声明的变量会放到以 <code>.initcall</code>开头命名的段中，每个级别对应一个 <code>.initcall</code>段，而这些段又会按顺序放到 <code>.init.data</code>段中。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// include/asm-generic/vmlinux.lds.h
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cp">#define INIT_CALLS_LEVEL(level)						\
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp">        __initcall##level##_start = .;				\
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cp">        KEEP(*(.initcall##level##.init))			\
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cp">        KEEP(*(.initcall##level##s.init))			\
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cp">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="cp">#define INIT_CALLS							\
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="cp">        __initcall_start = .;					\
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="cp">        KEEP(*(.initcallearly.init))				\
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(0)					\
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(1)					\
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(2)					\
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(3)					\
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(4)					\
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(5)					\
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(rootfs)				\
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(6)					\
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="cp">        INIT_CALLS_LEVEL(7)					\
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="cp">        __initcall_end = .;
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="cp">#define CON_INITCALL							\
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="cp">        __con_initcall_start = .;				\
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="cp">        KEEP(*(.con_initcall.init))				\
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="cp">        __con_initcall_end = .;
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// arch/arm64/kernel/vmlinux.lds.S
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">init</span><span class="p">.</span><span class="nl">data</span> <span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">INIT_DATA</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="nf">INIT_SETUP</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">INIT_CALLS</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">CON_INITCALL</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">INIT_RAM_FS</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="o">*</span><span class="p">(.</span><span class="n">init</span><span class="p">.</span><span class="n">altinstructions</span> <span class="p">.</span><span class="n">init</span><span class="p">.</span><span class="n">bss</span><span class="p">)</span>  <span class="cm">/* from the EFI stub */</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">.</span><span class="n">exit</span><span class="p">.</span><span class="nl">data</span> <span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">EXIT_DATA</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h2 id="26-initcall的执行时机">2.6. initcall的执行时机</h2>
<p>由initcall指定的函数会在do_pre_smp_initcalls和do_basic_setup执行。do_pre_smp_initcalls执行early_initcall指定的函数，这个是在多核处理器和调度系统初始化之前执行的。do_basic_setup会按initcall的级别，依次执行指定的函数。由于lds中没有根据函数名排序，同级别initcall指定的函数的执行顺序会由链接时initcall的布局决定。多次编译的顺序也可能不同。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// init/main.c
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="n">noinline</span> <span class="kt">void</span> <span class="n">__init</span> <span class="nf">kernel_init_freeable</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="c1">/// ... ...
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"></span>    <span class="nf">rcu_init_tasks_generic</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="nf">do_pre_smp_initcalls</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="nf">lockup_detector_init</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nf">smp_init</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nf">sched_init_smp</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nf">padata_init</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="nf">page_alloc_init_late</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="cm">/* Initialize page ext after all struct pages are initialized. */</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">early_page_ext_enabled</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nf">page_ext_init</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="nf">do_basic_setup</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1">/// ... ...
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span></code></pre></div><p><figure>
  <picture>

    
      
        
        
        
        
        
        
    <img
      loading="lazy"
      decoding="async"
      alt="initcall_func"
      
        class="image_figure image_internal image_unprocessed"
        src="initcall_func.png"
      
      
    />

    </picture>
</figure>
</p>
<h1 id="3-module使能">3. MODULE使能</h1>
<p>Linux中有些模块既可以链接到内核，也可以选择编译为ko，而这些模块的初始化函数可能是以initcall方式指定的。为了两者相互兼容，会把initcall定义为module_init。</p>
<p>下面分析module_init的实现，源码见《module_init源码》</p>
<ul>
<li><code>__copy(initfn)</code>：从initfn复制函数属性，从gcc-9开始支持。</li>
<li><code>__attribute__((alias(#initfn)))</code>：为init_module创建别名，指向原来的initfn。</li>
<li><code>___ADDRESSABLE(init_module, __initdata)</code>：声明一个initcall_t变量，并放到 <code>.init.data</code>段，变量名类似 <code>__UNIQUE_ID___addressable_init_module326</code>。</li>
</ul>
<p><code>__inittest</code>：代码中没有找到调用的地方，但是从v2.6.0对<a href="https://elixir.bootlin.com/linux/v2.6.0/source/include/linux/init.h#L157">module_init</a>的注释来看，猜测是为了防止编译器警告。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="cm">/* These macros create a dummy inline: gcc 2.9x does not count alias
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="cm"> as usage, hence the `unused function&#39; warning when __init functions
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="cm"> are declared static. We use the dummy __*_module_inline functions
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="cm"> both to kill the warning and check the type of the init/cleanup
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="cm"> function. */</span>
</span></span></code></pre></div><p>init_module是initfn的别名，其地址也是相同的，但是initfn通常会是static函数，而init_module是一个global函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">Disassembly</span> <span class="n">of</span> <span class="n">section</span> <span class="p">.</span><span class="n">init</span><span class="p">.</span><span class="nl">text</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="mo">0000000000000000</span> <span class="o">&lt;</span><span class="n">init_module</span><span class="o">&gt;:</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nf">hello_init</span><span class="p">()</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">   <span class="mi">0</span><span class="o">:</span>   <span class="n">d503201f</span>        <span class="n">nop</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">   <span class="mi">4</span><span class="o">:</span>   <span class="n">d503201f</span>        <span class="n">nop</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">/// t代表static，T代表global
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="mo">0000000000000000</span> <span class="mo">00000000000000</span><span class="n">c8</span> <span class="n">t</span> <span class="n">hello_init</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="mo">0000000000000000</span> <span class="mo">00000000000000</span><span class="n">c8</span> <span class="n">T</span> <span class="n">init_module</span>
</span></span></code></pre></div><h2 id="31-module_init源码">3.1. module_init源码</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// include/linux/module.h
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">/// ... ...
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span><span class="cp">#else </span><span class="cm">/* MODULE */</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cm"> * In most cases loadable modules do not need custom
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="cm"> * initcall levels. There are still some valid cases where
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="cm"> * a driver may be needed early if built in, and does not
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="cm"> * matter when built as a loadable module. Like bus
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="cm"> * snooping debug drivers.
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="cp">#define early_initcall(fn)              module_init(fn)
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="cp">#define core_initcall(fn)               module_init(fn)
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="cp">#define core_initcall_sync(fn)          module_init(fn)
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="cp">#define postcore_initcall(fn)           module_init(fn)
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="cp">#define postcore_initcall_sync(fn)      module_init(fn)
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="cp">#define arch_initcall(fn)               module_init(fn)
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="cp">#define subsys_initcall(fn)             module_init(fn)
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="cp">#define subsys_initcall_sync(fn)        module_init(fn)
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="cp">#define fs_initcall(fn)                 module_init(fn)
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="cp">#define fs_initcall_sync(fn)            module_init(fn)
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="cp">#define rootfs_initcall(fn)             module_init(fn)
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="cp">#define device_initcall(fn)             module_init(fn)
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="cp">#define device_initcall_sync(fn)        module_init(fn)
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="cp">#define late_initcall(fn)               module_init(fn)
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="cp">#define late_initcall_sync(fn)          module_init(fn)
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="cp">#define console_initcall(fn)            module_init(fn)
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="cm">/* Each module must use one module_init(). */</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="cp">#define module_init(initfn)                                     \
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="cp">        static inline initcall_t __maybe_unused __inittest(void)                \
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="cp">        { return initfn; }                                      \
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="cp">        int init_module(void) __copy(initfn)                    \
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="cp">                __attribute__((alias(#initfn)));                \
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="cp">        ___ADDRESSABLE(init_module, __initdata);
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="cm">/* This is only required if you want to be unloadable. */</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="cp">#define module_exit(exitfn)                                     \
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="cp">        static inline exitcall_t __maybe_unused __exittest(void)                \
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="cp">        { return exitfn; }                                      \
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="cp">        void cleanup_module(void) __copy(exitfn)                \
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="cp">                __attribute__((alias(#exitfn)));                \
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="cp">        ___ADDRESSABLE(cleanup_module, __exitdata);
</span></span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="cp">#endif
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">/// include/linux/init.h
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="cp">#define __initdata      __section(&#34;.init.data&#34;)
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// include/linux/compiler.h
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cm">/*
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cm"> * Force the compiler to emit &#39;sym&#39; as a symbol, so that we can reference
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cm"> * it from inline assembler. Necessary in case &#39;sym&#39; could be inlined
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cm"> * otherwise, or eliminated entirely due to lack of references that are
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cm"> * visible to the compiler.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="cp">#define ___ADDRESSABLE(sym, __attrs) \
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="cp">    static void * __used __attrs \
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="cp">        __UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)&amp;sym;
</span></span></span></code></pre></div><h2 id="32-init_module的执行时机">3.2. init_module的执行时机</h2>
<p>命令行下使用 <code>insmod</code>或 <code>modprobe</code>安装模块，最终系统调用为 <code>init_module</code>或 <code>finit_module</code>。
可以使用 <code>strace insmod test.ko</code>查看使用的具体的系统调用。</p>
<p>系统调用init_module和finit_module用来从用户态加载ko文件，<code>man 2 init_module</code>可以看到两者的介绍。init_module接收一个ELF文件的路径，而finit_module接收一个文件描述符。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">/// kernel/module/main.c
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="nf">SYSCALL_DEFINE3</span><span class="p">(</span><span class="n">init_module</span><span class="p">,</span> <span class="kt">void</span> <span class="n">__user</span> <span class="o">*</span><span class="p">,</span> <span class="n">umod</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="kt">unsigned</span> <span class="kt">long</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="p">,</span> <span class="n">uargs</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="c1">/// ... ...
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="nf">load_module</span><span class="p">(</span><span class="o">&amp;</span><span class="n">info</span><span class="p">,</span> <span class="n">uargs</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nf">SYSCALL_DEFINE3</span><span class="p">(</span><span class="n">finit_module</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="p">,</span> <span class="n">uargs</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span> <span class="n">flags</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1">/// ... ...
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span>    <span class="k">return</span> <span class="nf">load_module</span><span class="p">(</span><span class="o">&amp;</span><span class="n">info</span><span class="p">,</span> <span class="n">uargs</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>init_module和finit_module最后都会调到load_module，load_module的流程如下：</p>
<p><figure>
  <picture>

    
      
        
        
        
        
        
        
    <img
      loading="lazy"
      decoding="async"
      alt="init_module"
      
        class="image_figure image_internal image_unprocessed"
        src="init_module.png"
      
      
    />

    </picture>
</figure>
</p>
<h1 id="4-参考资料">4. 参考资料</h1>
<ol>
<li><a href="https://blog.csdn.net/tyustli/article/details/102535483">__attribute__((alias)) 变量属性</a></li>
<li><a href="https://blog.csdn.net/tyustli/article/details/102535483">__attribute__((alias)) 变量属性</a></li>
<li><a href="https://blog.csdn.net/tyustli/article/details/102535281">__attribute__((alias)) 函数属性</a></li>
<li><a href="https://blog.csdn.net/bugouyonggan/article/details/8136938">linux 内核驱动中__attribute__((alias(#x)))别名问题</a></li>
</ol>
<p><a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute">https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute</a>
<a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alias-function-attribute">https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alias-function-attribute</a>
<a href="https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#__COUNTER__">gcc __COUNTER__</a></p>

    </div><div class="post_comments">
  
  
  
</div>



  </article>
<aside class="sidebar">
  <section class="sidebar_inner">
    <br>
    
  
  <div class="search">
    <input type="search" class="search_field form_field" placeholder='搜索内容...' id="find" autocomplete="off" data-scope='post'>
    <label for="find" class="search_label"><svg class="icon">
  <title>search</title>
  <use xlink:href="#search"></use>
</svg>

    </label>
    
    <div class="search_results results"></div>
  </div>

        <div class="author_header">
          <img src="https://kingdix10.gitee.io/logos/icon_yellow_transparent.png" alt="kingdix10 photo">
          <h2>kingdix10</h2>
        </div>
      <div class="author_bio">
        拾月国度
      </div>
      <a href='https://kingdix10.gitee.io/about/' class="button mt-1" role="button" title='阅读更多'>阅读更多</a>

    
      
    
    <h2 class="mt-4">最新文章</h2>
    <ul class="flex-column">
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.6/kdump_crash/arm64_setup/" class="nav-link" title="ARM64 Crash调试环境搭建">ARM64 Crash调试环境搭建</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.6/kdump_crash/help/" class="nav-link" title="Crash帮助信息">Crash帮助信息</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/thermal/thermal/" class="nav-link" title="linux thermal子系统简介">linux thermal子系统简介</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/time/clocksource_clockevent/" class="nav-link" title="linux内核时间子系统（三）">linux内核时间子系统（三）</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/time/timekeeping/" class="nav-link" title="linux内核时间子系统（二）">linux内核时间子系统（二）</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/time/tim/" class="nav-link" title="linux内核时间子系统（一）">linux内核时间子系统（一）</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/device_driver/device_model/" class="nav-link" title="Linux内核驱动模型（四）核心结构体">Linux内核驱动模型（四）核心结构体</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/device_driver/initcall/" class="nav-link" title="Linux内核驱动模型（三）驱动初始化">Linux内核驱动模型（三）驱动初始化</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/fdt/dt_to_dt/" class="nav-link" title="Linux内核驱动模型（二）设备树转换">Linux内核驱动模型（二）设备树转换</a>
      </li>
      <li>
        <a href="https://kingdix10.gitee.io/post/kernel/linux-6.1/fdt/fdt_dt/" class="nav-link" title="Linux内核驱动模型（一）设备树展开">Linux内核驱动模型（一）设备树展开</a>
      </li>
    </ul>
    <div>
      <h2 class="mt-4 taxonomy" id="categories-section">分类</h2>
      <nav class="tags_nav">
        <a href='https://kingdix10.gitee.io/categories/%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86/' class="post_tag button button_translucent" title="进程管理">
          进程管理
          <span class="button_tally">11</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E8%AE%BE%E5%A4%87%E6%A8%A1%E5%9E%8B/' class="post_tag button button_translucent" title="设备模型">
          设备模型
          <span class="button_tally">5</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/4412/' class="post_tag button button_translucent" title="4412">
          4412
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/c%E8%AF%AD%E8%A8%80/' class="post_tag button button_translucent" title="c语言">
          C语言
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/' class="post_tag button button_translucent" title="启动流程">
          启动流程
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E6%97%B6%E9%97%B4%E5%AD%90%E7%B3%BB%E7%BB%9F/' class="post_tag button button_translucent" title="时间子系统">
          时间子系统
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/kdump-crash/' class="post_tag button button_translucent" title="kdump-crash">
          KDUMP-CRASH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/' class="post_tag button button_translucent" title="环境搭建">
          环境搭建
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/linux%E5%91%BD%E4%BB%A4/' class="post_tag button button_translucent" title="linux命令">
          LINUX命令
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/thermal%E5%AD%90%E7%B3%BB%E7%BB%9F/' class="post_tag button button_translucent" title="thermal子系统">
          THERMAL子系统
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/' class="post_tag button button_translucent" title="内存管理">
          内存管理
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E5%86%85%E6%A0%B8%E5%9F%BA%E7%A1%80/' class="post_tag button button_translucent" title="内核基础">
          内核基础
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/categories/%E5%86%85%E6%A0%B8%E8%B0%83%E8%AF%95/' class="post_tag button button_translucent" title="内核调试">
          内核调试
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
    <div>
      <h2 class="mt-4 taxonomy" id="series-section">专栏</h2>
      <nav class="tags_nav">
        <a href='https://kingdix10.gitee.io/series/%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86/' class="post_tag button button_translucent" title="进程管理">
          进程管理
          <span class="button_tally">11</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/series/%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A%A8%E6%A8%A1%E5%9E%8B/' class="post_tag button button_translucent" title="设备驱动模型">
          设备驱动模型
          <span class="button_tally">5</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/series/%E6%97%B6%E9%97%B4%E5%AD%90%E7%B3%BB%E7%BB%9F/' class="post_tag button button_translucent" title="时间子系统">
          时间子系统
          <span class="button_tally">3</span>
        </a>
        
        
      </nav>
    </div>
    <div>
      <h2 class="mt-4 taxonomy" id="tags-section">标签</h2>
      <nav class="tags_nav">
        <a href='https://kingdix10.gitee.io/tags/linux%E5%86%85%E6%A0%B8/' class="post_tag button button_translucent" title="linux内核">
          LINUX内核
          <span class="button_tally">19</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/linux-6.1/' class="post_tag button button_translucent" title="linux-6.1">
          LINUX-6.1
          <span class="button_tally">12</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/linux-6.6/' class="post_tag button button_translucent" title="linux-6.6">
          LINUX-6.6
          <span class="button_tally">9</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E5%86%85%E6%A0%B8%E9%A9%B1%E5%8A%A8/' class="post_tag button button_translucent" title="内核驱动">
          内核驱动
          <span class="button_tally">9</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86/' class="post_tag button button_translucent" title="进程管理">
          进程管理
          <span class="button_tally">6</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/linux/' class="post_tag button button_translucent" title="linux">
          LINUX
          <span class="button_tally">5</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/4412/' class="post_tag button button_translucent" title="4412">
          4412
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/c%E8%AF%AD%E8%A8%80/' class="post_tag button button_translucent" title="c语言">
          C语言
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/' class="post_tag button button_translucent" title="启动流程">
          启动流程
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E5%B7%A5%E5%85%B7/' class="post_tag button button_translucent" title="工具">
          工具
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/kdump-crash/' class="post_tag button button_translucent" title="kdump-crash">
          KDUMP-CRASH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/' class="post_tag button button_translucent" title="环境搭建">
          环境搭建
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/arm64/' class="post_tag button button_translucent" title="arm64">
          ARM64
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/u-boot/' class="post_tag button button_translucent" title="u-boot">
          U-BOOT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/' class="post_tag button button_translucent" title="内存管理">
          内存管理
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E5%86%85%E6%A0%B8%E8%B0%83%E8%AF%95/' class="post_tag button button_translucent" title="内核调试">
          内核调试
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/' class="post_tag button button_translucent" title="数据结构">
          数据结构
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://kingdix10.gitee.io/tags/%E8%B0%83%E8%AF%95/' class="post_tag button button_translucent" title="调试">
          调试
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
  </section>
</aside>

  
</div>
    </main><svg width="0" height="0" class="hidden">
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="facebook">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h151V331h-60v-90h60v-61c0-49.629 40.371-90 90-90h91v90h-91v61h91l-15 90h-76v181h121c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18.001 18.001" id="twitter">
    <path d="M15.891 4.013c.808-.496 1.343-1.173 1.605-2.034a8.68 8.68 0 0 1-2.351.861c-.703-.756-1.593-1.14-2.66-1.14-1.043 0-1.924.366-2.643 1.078a3.56 3.56 0 0 0-1.076 2.605c0 .309.039.585.117.819-3.076-.105-5.622-1.381-7.628-3.837-.34.601-.51 1.213-.51 1.846 0 1.301.549 2.332 1.645 3.089-.625-.053-1.176-.211-1.645-.47 0 .929.273 1.705.82 2.388a3.623 3.623 0 0 0 2.115 1.291c-.312.08-.641.118-.979.118-.312 0-.533-.026-.664-.083.23.757.664 1.371 1.291 1.841a3.652 3.652 0 0 0 2.152.743C4.148 14.173 2.625 14.69.902 14.69c-.422 0-.721-.006-.902-.038 1.697 1.102 3.586 1.649 5.676 1.649 2.139 0 4.029-.542 5.674-1.626 1.645-1.078 2.859-2.408 3.639-3.974a10.77 10.77 0 0 0 1.172-4.892v-.468a7.788 7.788 0 0 0 1.84-1.921 8.142 8.142 0 0 1-2.11.593z"
      ></path>
  </symbol>
  <symbol aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="mail">
    <path  d="M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="calendar">
    <path d="M452 40h-24V0h-40v40H124V0H84v40H60C26.916 40 0 66.916 0 100v352c0 33.084 26.916 60 60 60h392c33.084 0 60-26.916 60-60V100c0-33.084-26.916-60-60-60zm20 412c0 11.028-8.972 20-20 20H60c-11.028 0-20-8.972-20-20V188h432v264zm0-304H40v-48c0-11.028 8.972-20 20-20h24v40h40V80h264v40h40V80h24c11.028 0 20 8.972 20 20v48z"></path>
    <path d="M76 230h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 310h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 390h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80-80h40v40h-40z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="github">
    <path d="M255.968 5.329C114.624 5.329 0 120.401 0 262.353c0 113.536 73.344 209.856 175.104 243.872 12.8 2.368 17.472-5.568 17.472-12.384 0-6.112-.224-22.272-.352-43.712-71.2 15.52-86.24-34.464-86.24-34.464-11.616-29.696-28.416-37.6-28.416-37.6-23.264-15.936 1.728-15.616 1.728-15.616 25.696 1.824 39.2 26.496 39.2 26.496 22.848 39.264 59.936 27.936 74.528 21.344 2.304-16.608 8.928-27.936 16.256-34.368-56.832-6.496-116.608-28.544-116.608-127.008 0-28.064 9.984-51.008 26.368-68.992-2.656-6.496-11.424-32.64 2.496-68 0 0 21.504-6.912 70.4 26.336 20.416-5.696 42.304-8.544 64.096-8.64 21.728.128 43.648 2.944 64.096 8.672 48.864-33.248 70.336-26.336 70.336-26.336 13.952 35.392 5.184 61.504 2.56 68 16.416 17.984 26.304 40.928 26.304 68.992 0 98.72-59.84 120.448-116.864 126.816 9.184 7.936 17.376 23.616 17.376 47.584 0 34.368-.32 62.08-.32 70.496 0 6.88 4.608 14.88 17.6 12.352C438.72 472.145 512 375.857 512 262.353 512 120.401 397.376 5.329 255.968 5.329z"></path>
  </symbol>

  <symbol width="128px" height="128px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="gitee">
      <g id="LOGO" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
          <g id="Artboard-7" transform="translate(-192.000000, -115.000000)" fill="#C71D23">
              <path d="M228,115 C247.882251,115 264,131.117749 264,151 C264,170.882251 247.882251,187 228,187 C208.117749,187 192,170.882251 192,151 C192,131.117749 208.117749,115 228,115 Z M246.223335,131 C246.222967,131 246.2226,131 246.222232,131.001102 L221.33326,131.001102 C213.969504,131.001102 208,136.970606 208,144.334362 L208,169.222232 C208,170.204066 208.795934,171 209.777768,171 L236.000329,171 C242.627564,171 248,165.627564 248,159.000329 L248,148.778425 C248,147.796591 247.204066,147.000657 246.222232,147.000657 L225.7779,147.000657 C224.796248,147.001123 224.000389,147.796773 223.999667,148.778425 L223.998503,153.222667 C223.997802,154.155409 224.715909,154.920565 225.629522,154.994969 L225.775805,155.00042 L225.775805,155.00042 L238.222276,155.000317 C239.155019,155.000295 239.919992,155.718618 239.994164,156.63225 L240.000044,156.77807 L240.000044,156.77807 L240.000044,157.666909 C240.000044,160.612411 237.612243,163.000213 234.66674,163.000213 L217.776621,163.000213 C216.794928,163.000164 215.999101,162.204358 215.999025,161.222665 L215.998559,144.334184 C215.998337,141.462319 218.268172,139.120556 221.111731,139.005187 L221.331716,139.00088 L221.331716,139.00088 L246.21727,139.00088 C247.198674,138.999777 247.994429,138.204515 247.996141,137.223112 L247.998897,132.77887 C248.000609,131.797037 247.205169,131.000609 246.223335,131 Z" id="logo_gitee_g_red"></path>
          </g>
      </g>
  </symbol>

  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 212 212" id="gitlab">
    <path d="M12.3 74.7h54L43.3 3c-1-3.6-6.4-3.6-7.6 0L12.3 74.8z" />
    <path d="M12.3 74.7L.5 111c-1 3.2 0 6.8 3 8.8l101.6 74-92.5-119z"/>
    <path d="M105 193.7l-38.6-119h-54l92.7 119z"/>
    <path d="M105 193.7l38.7-119H66.4l38.7 119z"/>
    <path d="M105 193.7l38.7-119H198l-93 119z"/>
    <path d="M198 74.7l11.6 36.2c1 3 0 6.6-3 8.6l-101.5 74 93-119z"/>
    <path d="M198 74.7h-54.3L167 3c1.2-3.6 6.4-3.6 7.6 0L198 74.8z"/>
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="rss">
    <circle cx="3.429" cy="20.571" r="3.429"></circle>
    <path d="M11.429 24h4.57C15.999 15.179 8.821 8.001 0 8v4.572c6.302.001 11.429 5.126 11.429 11.428z"></path>
    <path d="M24 24C24 10.766 13.234 0 0 0v4.571c10.714 0 19.43 8.714 19.43 19.429z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="linkedin">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h362c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zM181 406h-60V196h60zm0-240h-60v-60h60zm210 240h-60V286c0-16.54-13.46-30-30-30s-30 13.46-30 30v120h-60V196h60v11.309C286.719 202.422 296.93 196 316 196c40.691.043 75 36.547 75 79.688zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 612" id="to-top">
    <path d="M604.501 440.509L325.398 134.956c-5.331-5.357-12.423-7.627-19.386-7.27-6.989-.357-14.056 1.913-19.387 7.27L7.499 440.509c-9.999 10.024-9.999 26.298 0 36.323s26.223 10.024 36.222 0l262.293-287.164L568.28 476.832c9.999 10.024 26.222 10.024 36.221 0 9.999-10.023 9.999-26.298 0-36.323z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="carly">
    <path d="M504.971 239.029L448 182.059V84c0-46.317-37.682-84-84-84h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c19.851 0 36 16.149 36 36v108c0 6.365 2.529 12.47 7.029 16.971L454.059 256l-47.029 47.029A24.002 24.002 0 0 0 400 320v108c0 19.851-16.149 36-36 36h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c46.318 0 84-37.683 84-84v-98.059l56.971-56.971c9.372-9.372 9.372-24.568 0-33.941zM112 192V84c0-19.851 16.149-36 36-36h44c13.255 0 24-10.745 24-24S205.255 0 192 0h-44c-46.318 0-84 37.683-84 84v98.059l-56.971 56.97c-9.373 9.373-9.373 24.568 0 33.941L64 329.941V428c0 46.317 37.682 84 84 84h44c13.255 0 24-10.745 24-24s-10.745-24-24-24h-44c-19.851 0-36-16.149-36-36V320c0-6.365-2.529-12.47-7.029-16.971L57.941 256l47.029-47.029A24.002 24.002 0 0 0 112 192z"></path>
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="copy">
    <path d="M23 2.75A2.75 2.75 0 0 0 20.25 0H8.75A2.75 2.75 0 0 0 6 2.75v13.5A2.75 2.75 0 0 0 8.75 19h11.5A2.75 2.75 0 0 0 23 16.25zM18.25 14.5h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5z"></path>
    <path d="M8.75 20.5a4.255 4.255 0 0 1-4.25-4.25V2.75c0-.086.02-.166.025-.25H3.75A2.752 2.752 0 0 0 1 5.25v16A2.752 2.752 0 0 0 3.75 24h12a2.752 2.752 0 0 0 2.75-2.75v-.75z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.001 512.001" id="closeme">
    <path d="M284.286 256.002L506.143 34.144c7.811-7.811 7.811-20.475 0-28.285-7.811-7.81-20.475-7.811-28.285 0L256 227.717 34.143 5.859c-7.811-7.811-20.475-7.811-28.285 0-7.81 7.811-7.811 20.475 0 28.285l221.857 221.857L5.858 477.859c-7.811 7.811-7.811 20.475 0 28.285a19.938 19.938 0 0 0 14.143 5.857 19.94 19.94 0 0 0 14.143-5.857L256 284.287l221.857 221.857c3.905 3.905 9.024 5.857 14.143 5.857s10.237-1.952 14.143-5.857c7.811-7.811 7.811-20.475 0-28.285L284.286 256.002z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="open-menu">
    <path d="M492 236H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0-160H20C8.954 76 0 84.954 0 96s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0 320H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="instagram">
    <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id=youtube>
    <path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="stackoverflow">
    <path d="M21 27v-8h3v11H0V19h3v8h18z"></path><path d="M17.1.2L15 1.8l7.9 10.6 2.1-1.6L17.1.2zm3.7 14.7L10.6 6.4l1.7-2 10.2 8.5-1.7 2zM7.2 12.3l12 5.6 1.1-2.4-12-5.6-1.1 2.4zm-1.8 6.8l13.56 1.96.17-2.38-13.26-2.55-.47 2.97zM19 25H5v-3h14v3z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="xing">
    <path d="M18.188 0c-.517 0-.741.325-.927.66 0 0-7.455 13.224-7.702 13.657.015.024 4.919 9.023 4.919 9.023.17.308.436.66.967.66h3.454c.211 0 .375-.078.463-.22.089-.151.089-.346-.009-.536l-4.879-8.916c-.004-.006-.004-.016 0-.022L22.139.756c.095-.191.097-.387.006-.535C22.056.078 21.894 0 21.686 0h-3.498zM3.648 4.74c-.211 0-.385.074-.473.216-.09.149-.078.339.02.531l2.34 4.05c.004.01.004.016 0 .021L1.86 16.051c-.099.188-.093.381 0 .529.085.142.239.234.45.234h3.461c.518 0 .766-.348.945-.667l3.734-6.609-2.378-4.155c-.172-.315-.434-.659-.962-.659H3.648v.016z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 71 55" id="discord">
    <path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 18" id="mastodon">
    <path
    fill="#ffffff"
    d="m 15.054695,9.8859583 c -0.22611,1.1632697 -2.02517,2.4363497 -4.09138,2.6830797 -1.0774504,0.12856 -2.1382704,0.24673 -3.2694704,0.19484 -1.84996,-0.0848 -3.30971,-0.44157 -3.30971,-0.44157 0,0.1801 0.0111,0.35157 0.0333,0.51194 0.24051,1.82571 1.81034,1.93508 3.29737,1.98607 1.50088,0.0514 2.8373104,-0.37004 2.8373104,-0.37004 l 0.0617,1.35686 c 0,0 -1.0498104,0.56374 -2.9199404,0.66742 -1.03124,0.0567 -2.3117,-0.0259 -3.80308,-0.42069 -3.23454998,-0.85613 -3.79081998,-4.304 -3.87592998,-7.8024197 -0.026,-1.03871 -0.01,-2.01815 -0.01,-2.83732 0,-3.57732 2.34385998,-4.62587996 2.34385998,-4.62587996 1.18184,-0.54277 3.20976,-0.77101 5.318,-0.7882499985409 h 0.0518 C 9.8267646,0.01719834 11.856025,0.24547834 13.037775,0.78824834 c 0,0 2.34377,1.04855996 2.34377,4.62587996 0,0 0.0294,2.63937 -0.32687,4.47183"/>
 <path
    fill="#000000"
    d="m 12.616925,5.6916583 v 4.3315297 h -1.71607 V 5.8189683 c 0,-0.88624 -0.37289,-1.33607 -1.1187604,-1.33607 -0.82467,0 -1.23799,0.53361 -1.23799,1.58875 v 2.30122 h -1.70594 v -2.30122 c 0,-1.05514 -0.4134,-1.58875 -1.23808,-1.58875 -0.74587,0 -1.11876,0.44983 -1.11876,1.33607 v 4.2042197 h -1.71607 V 5.6916583 c 0,-0.88527 0.22541,-1.58876 0.67817,-2.10922 0.46689,-0.52047 1.07833,-0.78727 1.83735,-0.78727 0.87816,0 1.54317,0.33752 1.98288,1.01267 l 0.42744,0.71655 0.42753,-0.71655 c 0.43961,-0.67515 1.10463,-1.01267 1.9828704,-1.01267 0.75893,0 1.37037,0.2668 1.83735,0.78727 0.45268,0.52046 0.67808,1.22395 0.67808,2.10922"/>
  </symbol>
</svg>

<footer class="footer">
  <div class="footer_inner wrap pale">
    <img src='https://kingdix10.gitee.io/icons/copy.svg' class="icon icon_2 transparent" alt="拾月国度">
    <p>Copyright&nbsp;2018-&nbsp;<span class="year"></span>&nbsp;拾月国度. All Rights Reserved</p><a class="to_top" href="#documentTop">
  <svg class="icon">
  <title>to-top</title>
  <use xlink:href="#to-top"></use>
</svg>

</a>

  </div>
</footer>

<script type="text/javascript" src="https://kingdix10.gitee.io/zh-cn/js/bundle.352f6b8ac853443fc909370d968a769ffa303b36042cc66849f2d48d9e5dd951ee86c06130908f5d77ea0e55ec8fed0e5dc26f0f14bbd4ad6dcf35999232e5bc.js" integrity="sha512-NS9rishTRD/JCTcNlop2n/owOzYELMZoSfLUjZ5d2VHuhsBhMJCPXXfqDlXsj&#43;0OXcJvDxS71K1tzzWZkjLlvA==" crossorigin="anonymous"></script>

  <script src="https://kingdix10.gitee.io/js/search.min.b19f217359693afb8f0abd75ca8de6becceec41f5304950fc48e165914ef227f44d10005d02a281a66e33b482e2ff27e6eb893111505deb4f072c307e1f887bb.js"></script>

  </body>
</html>
